package org.smth.search.fetcher.impl;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.smth.search.fetcher.PageFetcher;

public class PageFetcherImpl implements PageFetcher {

	private Log log = LogFactory.getLog(this.getClass());

	private HttpClient client;

	private synchronized void initHttpClient() {
		if (client != null) {
			try {
				HttpConnectionManager manager = client.getHttpConnectionManager();
				if (manager != null) {
					manager.closeIdleConnections(1);
				}
				client = null;
			} catch (Throwable t) {
				t.printStackTrace();
			}
		}
		HttpClientParams params = new HttpClientParams();
		params.setContentCharset("GB18030");
		this.client = new HttpClient(params);
	}

	private PageFetcherImpl() {
		this.initHttpClient();
	}

	private int tryTimes = 4;

	private long timeout = 120000;

	public synchronized String fetchPage(String url) {
		return fetchPage(url, tryTimes);
	}

	private String fetchPage(String url, int tryTimes) {
		RuntimeException t = null;
		for (int i = 0; i < tryTimes; i++) {
			Object[] result = new Object[1];
			fetchPage(url, result, timeout);
			Object obj = result[0];
			if (obj instanceof String) {
				return (String) obj;
			} else if (obj instanceof Throwable) {
				if (obj instanceof RuntimeException) {
					t = (RuntimeException) obj;
				} else {
					t = new RuntimeException((Throwable) obj);
				}
			} else {
				Integer n = (Integer) obj;
				if (n == 1) {
					if (i < (tryTimes - 1)) {
						log.warn("超时,重置httpclient");
						this.initHttpClient();
					}
				}
			}
		}
		if (t == null) {
			t = new RuntimeException("超时或者没有内容");
		}
		throw t;
	}

	private void fetchPage(final String url, final Object[] result, long timeout) {
		Thread thread = new Thread() {
			public void run() {
				try {
					result[0] = fetchPageReal(url);
				} catch (Throwable t) {
					result[0] = t;
				} finally {
					if (result[0] == null) {
						result[0] = 0;
					}
				}
			}
		};
		thread.setDaemon(true);
		thread.start();
		long start = System.currentTimeMillis();
		try {
			while (result[0] == null && (System.currentTimeMillis() - start) < timeout) {
				Thread.sleep(200);
			}
		} catch (InterruptedException e) {
			throw new RuntimeException("被打断了");
		}
		if (result[0] == null) {
			result[0] = 1;
		}
	}

	private String fetchPageReal(String url) {
		GetMethod get = new GetMethod(url);
		try {
			int status = client.executeMethod(get);
			if (status != 200) {
				throw new RuntimeException("访问" + url + "时的回应不是200,而是" + status);
			}
			return get.getResponseBodyAsString();
		} catch (Exception e) {
			RuntimeException ex;
			if (e instanceof RuntimeException) {
				ex = (RuntimeException) e;
			} else {
				ex = new RuntimeException(e);
			}
			throw ex;
		}
	}

}
